﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace RM.BasicLibrary.Cryptographys
{
    /// <summary>
    /// 加密解密
    /// </summary>
    public interface ICrypt
    {
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="encode"></param>
        /// <returns></returns>
        string Encrypt(string encode);
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="decode"></param>
        /// <returns></returns>
        string Decrypt(string decode);
    }

    public class DESCrypt : ICrypt
    {
        /// <summary>
        /// 
        /// </summary>
        public string Key { get; set; } = "HQDCKEY1";
        /// <summary>
        ///  
        /// </summary>
        public string IV { get; set; } = "HQDCKEY2";

        public string Decrypt(string decode)
        {
            decode.NotNull();
            Key.NotNull();
            IV.NotNull();
            if (Key.Length != 8) throw new ParameterException($"{nameof(Key)}字符串长度必须为8位");
            if (IV.Length != 8) throw new ParameterException($"{nameof(IV)}字符串长度必须为8位");
            using (DESCryptoServiceProvider sa =
                new DESCryptoServiceProvider
                { Key = Encoding.UTF8.GetBytes(Key), IV = Encoding.UTF8.GetBytes(IV) })
            {
                using (ICryptoTransform ct = sa.CreateDecryptor())
                {
                    byte[] byt = Convert.FromBase64String(decode);

                    using (var ms = new MemoryStream())
                    {
                        using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
                        {
                            cs.Write(byt, 0, byt.Length);
                            cs.FlushFinalBlock();
                        }
                        return Encoding.UTF8.GetString(ms.ToArray());
                    }
                }
            }
        }

        public string Encrypt(string encode)
        {
            encode.NotNull();
            Key.NotNull();
            IV.NotNull();
            if (Key.Length != 8) throw new ParameterException($"{nameof(Key)}字符串长度必须为8位");
            if (IV.Length != 8) throw new ParameterException($"{nameof(IV)}字符串长度必须为8位");
            using (DESCryptoServiceProvider sa
                  = new DESCryptoServiceProvider { Key = Encoding.UTF8.GetBytes(Key), IV = Encoding.UTF8.GetBytes(IV) })
            {
                using (ICryptoTransform ct = sa.CreateEncryptor())
                {
                    byte[] by = Encoding.UTF8.GetBytes(encode);
                    using (var ms = new MemoryStream())
                    {
                        using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
                        {
                            cs.Write(by, 0, by.Length);
                            cs.FlushFinalBlock();
                        }
                        return Convert.ToBase64String(ms.ToArray());
                    }
                }
            }

        }
        public void SetDESCryptKeyIv(string key, string iv)
        {
            Key = key;
            IV = iv;
        }
    }
    /// <summary>
    /// 非对称加密
    /// </summary>
    public class RSACrypt : ICrypt
    {
        public string PrivateKeyPath { get; set; }
        public string PublicKeyPath { get; set; }
        /// <summary>
        /// 设置公钥私钥地址
        /// </summary>
        /// <param name="privateKeyPath"></param>
        /// <param name="publicKeyPath"></param>
        public void SetKeyPath(string privateKeyPath = "d:\\PrivateKey.xml", string publicKeyPath = "d:\\PublicKey.xml")
        {
            privateKeyPath.NotNull();
            publicKeyPath.NotNull();
            PrivateKeyPath = privateKeyPath;
            PublicKeyPath = publicKeyPath;
        }
        /// <summary>
        /// 创建RSA公钥私钥
        /// </summary>
        public void CreateRSAKey(string privateKeyPath = "d:\\PrivateKey.xml", string publicKeyPath = "d:\\PublicKey.xml")
        {
            SetKeyPath(privateKeyPath, publicKeyPath);
            //创建RSA对象
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            //生成RSA[公钥私钥]
            string privateKey = rsa.ToXmlString(true);
            string publicKey = rsa.ToXmlString(false);
            //将密钥写入指定路径
            File.WriteAllText(privateKeyPath, privateKey);//文件内包含公钥和私钥
            File.WriteAllText(publicKeyPath, publicKey);//文件内只包含公钥
        }
        public string Decrypt(string decode)
        {
            //C#默认只能使用[私钥]进行解密(想使用[私钥加密]可使用第三方组件BouncyCastle来实现)
            PrivateKeyPath.NotNull();
            decode.NotNull();
            string privateKey = File.ReadAllText(PrivateKeyPath);
            //创建RSA对象并载入[私钥]
            RSACryptoServiceProvider rsaPrivate = new RSACryptoServiceProvider();
            rsaPrivate.FromXmlString(privateKey);
            //对数据进行解密
            byte[] privateValue = rsaPrivate.Decrypt(Convert.FromBase64String(decode), false);//使用Base64将string转换为byte
            string privateStr = Encoding.UTF8.GetString(privateValue);
            return privateStr;
        }

        public string Encrypt(string encode)
        {
            encode.NotNull();
            //C#默认只能使用[公钥]进行加密(想使用[公钥解密]可使用第三方组件BouncyCastle来实现)
            string publicKey = File.ReadAllText(PublicKeyPath);
            //创建RSA对象并载入[公钥]
            RSACryptoServiceProvider rsaPublic = new RSACryptoServiceProvider();
            rsaPublic.FromXmlString(publicKey);
            //对数据进行加密
            byte[] publicValue = rsaPublic.Encrypt(Encoding.UTF8.GetBytes(encode), false);
            string publicStr = Convert.ToBase64String(publicValue);//使用Base64将byte转换为string
            return publicStr;
        }
    }

}
